<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Invoice;
use App\Models\Tenant;
use App\Models\LandingCompany;
use Carbon\Carbon;

class InvoiceSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $this->command->info('开始创建发票测试数据...');

        // 获取所有租户和落地公司
        $tenants = Tenant::all();
        $landingCompanies = LandingCompany::active()->get();
        
        if ($tenants->isEmpty()) {
            $this->command->warn('没有找到租户数据，请先运行 TenantSeeder');
            return;
        }

        if ($landingCompanies->isEmpty()) {
            $this->command->warn('没有找到落地公司数据，请先运行 LandingCompanySeeder');
            return;
        }

        // 开票类型权重分布
        $billingTypeWeights = [
            Invoice::BILLING_TYPE_6_REGULAR => 50,           // 6%普票 50%
            Invoice::BILLING_TYPE_6_SPECIAL => 35,           // 6%专票 35%
            Invoice::BILLING_TYPE_DIFFERENTIAL_REGULAR => 15  // 差额普票 15%
        ];

        // 开票状态权重分布
        $statusWeights = [
            Invoice::STATUS_NEW => 10,        // 新建 10%
            Invoice::STATUS_BILLING => 20,    // 开票中 20%
            Invoice::STATUS_BILLED => 50,     // 已开票 50%
            Invoice::STATUS_REJECTED => 10,   // 已拒绝 10%
            Invoice::STATUS_VOIDED => 10      // 已作废 10%
        ];

        // 发票内容模板
        $invoiceContents = [
            '信息技术服务费',
            '软件开发服务费',
            '系统维护服务费',
            '技术咨询服务费',
            '数据处理服务费',
            '网络建设服务费',
            '软件测试服务费',
            '系统集成服务费',
            '技术支持服务费',
            '信息系统运维服务费'
        ];

        // 关联任务模板
        $relatedTaskTemplates = [
            '项目开发任务 #PRJ2024001',
            '系统维护任务 #SYS2024002',
            '技术咨询任务 #CON2024003',
            '软件测试任务 #TEST2024004',
            '数据迁移任务 #DATA2024005',
            '网站建设任务 #WEB2024006',
            '移动应用开发任务 #APP2024007',
            '数据库优化任务 #DB2024008',
            '安全评估任务 #SEC2024009',
            '性能优化任务 #PERF2024010'
        ];

        // 拒绝原因模板
        $rejectionReasons = [
            '发票信息填写不完整',
            '税号格式不正确',
            '开票金额与实际不符',
            '发票抬头信息有误',
            '银行账户信息错误',
            '发票内容描述不清',
            '附件资料不全',
            '审批流程未完成'
        ];

        // 快递单号前缀
        $expressPrefixes = ['SF', 'YTO', 'ZTO', 'STO', 'YD', 'HTKY', 'JD', 'EMS'];

        $totalInvoices = 0;

        foreach ($tenants as $tenant) {
            // 每个租户创建30-80条发票记录
            $invoiceCount = rand(30, 80);
            
            for ($i = 0; $i < $invoiceCount; $i++) {
                try {
                    // 根据权重选择开票类型和状态
                    $billingType = $this->getWeightedRandomChoice($billingTypeWeights);
                    $status = $this->getWeightedRandomChoice($statusWeights);
                    
                    // 生成申请时间（最近12个月内）
                    $applicationTime = Carbon::now()->subDays(rand(0, 365))->subHours(rand(0, 23))->subMinutes(rand(0, 59));
                    
                    // 生成发票金额
                    $invoiceAmount = $this->generateRealisticAmount($billingType);
                    
                    // 随机选择落地公司
                    $landingCompany = $landingCompanies->random();
                    
                    // 生成发票数据
                    $invoiceData = [
                        'tenant_id' => $tenant->id,
                        'landing_company_id' => $landingCompany->id,
                        'invoice_amount' => $invoiceAmount,
                        'billing_type' => $billingType,
                        'billing_category' => Invoice::BILLING_CATEGORY_IT_SERVICES,
                        'invoice_title' => $tenant->company_name ?? $tenant->name,
                        'tax_number' => $this->generateTaxNumber(),
                        'company_address' => $this->generateAddress(),
                        'company_phone' => $this->generatePhone(),
                        'bank_name' => $this->generateBankName(),
                        'bank_account' => $this->generateBankAccount(),
                        'invoice_content' => $invoiceContents[array_rand($invoiceContents)],
                        'related_tasks' => rand(0, 100) < 70 ? json_encode([$relatedTaskTemplates[array_rand($relatedTaskTemplates)]], JSON_UNESCAPED_UNICODE) : null,
                        'invoice_file_path' => $status === Invoice::STATUS_BILLED
                            ? sprintf('invoices/%s/invoice_%s.pdf', $tenant->id, uniqid())
                            : null,
                        'status' => $status,
                        'rejection_reason' => $status === Invoice::STATUS_REJECTED ? $rejectionReasons[array_rand($rejectionReasons)] : null,
                        'express_tracking_number' => $status === Invoice::STATUS_BILLED ? $this->generateExpressNumber($expressPrefixes) : null,
                        'invoice_remarks' => rand(0, 100) < 30 ? $this->generateRemarks() : null,
                        'application_time' => $applicationTime,
                        'processed_at' => in_array($status, [Invoice::STATUS_BILLED, Invoice::STATUS_REJECTED, Invoice::STATUS_VOIDED]) 
                            ? $applicationTime->copy()->addHours(rand(4, 72)) : null,
                        'issued_at' => $status === Invoice::STATUS_BILLED 
                            ? $applicationTime->copy()->addHours(rand(24, 120)) : null,
                        'created_by' => rand(1, 3),
                        'processed_by' => in_array($status, [Invoice::STATUS_BILLED, Invoice::STATUS_REJECTED, Invoice::STATUS_VOIDED]) 
                            ? rand(1, 5) : null,
                    ];

                    Invoice::create($invoiceData);
                    $totalInvoices++;

                } catch (\Exception $e) {
                    $this->command->warn("创建发票记录失败: " . $e->getMessage());
                    continue;
                }
            }
            
            $this->command->info("租户 {$tenant->company_name} 创建了 {$invoiceCount} 条发票记录");
        }

        $this->command->info("发票测试数据创建完成！总计创建 {$totalInvoices} 条记录");
    }

    /**
     * 根据权重随机选择
     */
    private function getWeightedRandomChoice($weights): string
    {
        $total = array_sum($weights);
        $random = rand(1, $total);
        $current = 0;
        
        foreach ($weights as $choice => $weight) {
            $current += $weight;
            if ($random <= $current) {
                return $choice;
            }
        }
        
        return array_key_first($weights);
    }

    /**
     * 生成真实的发票金额分布
     */
    private function generateRealisticAmount($billingType): float
    {
        $rand = rand(1, 100);
        
        // 不同开票类型的金额分布
        if ($billingType === Invoice::BILLING_TYPE_6_REGULAR) {
            // 6%普票：通常金额较小
            if ($rand <= 40) return rand(1000, 10000) + (rand(0, 99) / 100);
            if ($rand <= 70) return rand(10000, 50000) + (rand(0, 99) / 100);
            if ($rand <= 90) return rand(50000, 200000) + (rand(0, 99) / 100);
            return rand(200000, 500000) + (rand(0, 99) / 100);
        } elseif ($billingType === Invoice::BILLING_TYPE_6_SPECIAL) {
            // 6%专票：通常金额较大
            if ($rand <= 30) return rand(10000, 50000) + (rand(0, 99) / 100);
            if ($rand <= 60) return rand(50000, 200000) + (rand(0, 99) / 100);
            if ($rand <= 85) return rand(200000, 800000) + (rand(0, 99) / 100);
            return rand(800000, 2000000) + (rand(0, 99) / 100);
        } else { // 差额普票
            // 差额普票：金额适中
            if ($rand <= 50) return rand(5000, 30000) + (rand(0, 99) / 100);
            if ($rand <= 80) return rand(30000, 100000) + (rand(0, 99) / 100);
            return rand(100000, 300000) + (rand(0, 99) / 100);
        }
    }

    /**
     * 生成税务登记号
     */
    private function generateTaxNumber(): string
    {
        $regionCodes = ['110108', '310115', '440300', '440101', '330100', '510100', '420100', '610100', '320100', '370200'];
        $regionCode = $regionCodes[array_rand($regionCodes)];
        
        $orgCode = 'MA' . sprintf('%08d', rand(10000000, 99999999));
        $checkCode = rand(0, 9);
        
        return '91' . $regionCode . $orgCode . $checkCode;
    }

    /**
     * 生成公司地址
     */
    private function generateAddress(): string
    {
        $addresses = [
            '北京市海淀区中关村大街1号',
            '上海市浦东新区张江高科技园区',
            '深圳市南山区科技园南区',
            '广州市天河区珠江新城',
            '杭州市西湖区文三路259号',
            '成都市高新区天府三街69号',
            '武汉市东湖新技术开发区',
            '西安市高新区丈八一路',
            '南京市建邺区河西新城',
            '青岛市崂山区海尔路182号'
        ];
        
        return $addresses[array_rand($addresses)] . rand(1, 999) . '号' . rand(1, 50) . '楼' . rand(1, 30) . '层';
    }

    /**
     * 生成电话号码
     */
    private function generatePhone(): string
    {
        $areaCodes = ['010', '021', '0755', '020', '0571', '028', '027', '029', '025', '0532'];
        $areaCode = $areaCodes[array_rand($areaCodes)];
        
        return $areaCode . '-' . rand(20000000, 99999999);
    }

    /**
     * 生成银行名称
     */
    private function generateBankName(): string
    {
        $banks = [
            '中国工商银行',
            '中国建设银行',
            '中国银行',
            '中国农业银行',
            '招商银行',
            '交通银行',
            '中信银行',
            '光大银行',
            '华夏银行',
            '民生银行'
        ];
        
        return $banks[array_rand($banks)] . '股份有限公司';
    }

    /**
     * 生成银行账号
     */
    private function generateBankAccount(): string
    {
        return rand(1000, 9999) . ' ' . rand(1000, 9999) . ' ' . rand(1000, 9999) . ' ' . rand(1000, 9999);
    }

    /**
     * 生成快递单号
     */
    private function generateExpressNumber($prefixes): string
    {
        $prefix = $prefixes[array_rand($prefixes)];
        return $prefix . sprintf('%012d', rand(100000000000, 999999999999));
    }

    /**
     * 生成开票备注
     */
    private function generateRemarks(): string
    {
        $remarks = [
            '请尽快开具发票，用于报销',
            '发票内容请按照合同约定填写',
            '开票完成后请及时邮寄',
            '如有问题请联系财务部门',
            '发票抬头信息请仔细核对',
            '请开具增值税专用发票',
            '发票用途：企业所得税抵扣',
            '急件，请优先处理'
        ];
        
        return $remarks[array_rand($remarks)];
    }
}
